#ifndef __UNION_H__
#define __UNION_H__

#include <list>
#include <string>
#include <vector>
#include <unordered_map>
#include "../share/common_singleton.h"
#include "../share/retcodes.h"
#include "../share/common_define.h"
#include "../share/timer.h"
#include "../../3rd/libjson/json.h"
#include "playerinfo_mgr.h"

#define MAX_MEMBER_NUM		150
#define MAX_APPLY_NUM		50
#define MAX_INVITE_NUM		50

#define MAX_STRING_LEN		640
#define MAX_NAME_LEN		32


class CPlayerInfo;
class Player;
class CUnionAlcohol;

enum EGuildPower
{
	GUILD_POWER_APPOINT = 1, // 职位任免
	GUILD_POWER_HANDLE_APPLY = 2, // 批复入盟申请
	GUILD_POWER_KICKOUT = 3, // 踢人
	GUILD_POWER_DECLARE = 4, // 修改公告
	GUILD_POWER_SET = 5, // 修改仙盟设置
	GUILD_POWER_UPGRADE = 6, // 建筑升级
	GUILD_POWER_ACTIVITY = 7, // 开启活动
	GUILD_POWER_RENAME = 8, // 修改仙盟名字、图标
	GUILD_POWER_AWARD = 9, // 获取奖励
	GUILD_POWER_SIGNUP_BATTLE = 10, // 报名仙盟战;
};

enum EGuildTitle
{
	E_GUILD_TITLE_MEMBER = 1, // 普通成员
	E_GUILD_TITLE_VICE_CHAIRMAN = 3, // 副会长
	E_GUILD_TITLE_CHAIRMAN = 5, // 会长
};

//1加入公会 2退出公会 3权限改变 4创建公会
enum EGuildInfoChanged
{
	E_JOIN_GUILD = 1,
	E_LEAVE_GUILD = 2,
	E_PERMISSION_CHANGE = 3,
	E_CREATE_GUILD = 4,
};

class CGuildMember
{
public:
	CGuildMember();
	~CGuildMember();

	int32_t player_id() { return playerid_; }
	void set_player_id(int32_t playerid) { playerid_ = playerid; }

	int32_t join_time() { return join_time_; }
	void set_join_time(int32_t join_time) { join_time_ = join_time; }

	int32_t title() { return title_; }
	void set_title(int32_t title) { title_ = title; }

	int32_t total_contribution() const { return total_donation_; }
	void set_total_contribution(int32_t value) { total_donation_ = value; }

	int32_t week_donation()const { return week_donation_; }
	void set_week_donation(int32_t week) { week_donation_ = week; }
	int32_t day_donation()const { return day_donation_; }
	void set_day_donation(int32_t day) { day_donation_ = day; }

	int32_t gold_donationcount()const { return gold_donationcount_; }
	int32_t diamod_donationcount()const { return diamod_donationcount_; }
	int32_t ticket_donationcount()const { return ticket_donationcount_; }
	int32_t get_alcohol_id()const { return alcohol_id; }
	int32_t get_alcohol_count()const { return alcohol_count; }
	int32_t get_alcohol_expire()const { return alcohol_expire; }
	int32_t get_donationtime()const { return donationtime_; }
	void set_gold_donationcount(int32_t gold_don) { gold_donationcount_ = gold_don; }
	void set_diamod_donationcount(int32_t diamo_don) { diamod_donationcount_ = diamo_don; }
	void set_ticket_donationcount(int32_t ticket_don) { ticket_donationcount_ = ticket_don; }
	void set_alcohol_id(int32_t alcohol) { alcohol_id = alcohol; }
	void set_alcohol_count(int32_t alcohol, bool step = false) { 
		if (step == false) {
			alcohol_count = alcohol;
		}
		else {
			alcohol_count++;
		}
	}
	void set_alcohol_expire(int32_t alcohol) { alcohol_expire = alcohol; }
	void set_donationtime(int32_t donationtime) { donationtime_ = donationtime; }

	void add_donation(int32_t donation)
	{
		day_donation_ += donation;
		week_donation_ += donation;
		total_donation_ += donation;
	}
	void OnNewDay();
	void OnNewWeekDay();
private:
	int32_t playerid_;
	int32_t join_time_;
	int32_t title_;
	int32_t total_donation_; //历史总贡献
	int32_t week_donation_;		 //周贡献
	int32_t day_donation_;		 //日贡献
	int32_t gold_donationcount_;	//今日金币捐献次数
	int32_t diamod_donationcount_;	//今日钻石捐献次数
	int32_t ticket_donationcount_;	//今日点券(红钻)捐献次数
	int32_t alcohol_id;				// 酒id
	int32_t alcohol_count;			// 喝酒的数量
	int32_t alcohol_expire;			// 过期时间
	int32_t donationtime_;			// 捐献时间
};

enum EGuildNoticeType
{
	GUILD_NOTICE_MEM_JOIN = 1, // 新成员加入
	GUILD_NOTICE_RENAME = 2, // 盟主修改公会名字
	GUILD_NOTICE_IMAGE = 3, // 盟主修改公会图片
	GUILD_NOTICE_VICE_RENAME = 4, // 副盟主修改公会名字
	GUILD_NOTICE_VICE_IMAGE = 5, // 副盟主修改公会图片
	GUILD_NOTICE_DECLARE = 6, // 盟主修改公告
	GUILD_NOTICE_VICE_DECLARE = 7, // 副盟主修改公告
	GUILD_NOTICE_DECLARE_VOICE = 8, // 盟主修改语音公告
	GUILD_NOTICE_VICE_DECLARE_VOICE = 9, // 副盟主修改语音公告
	GUILD_NOTICE_TITLE_PROMOTE = 10,// 职位提升
	GUILD_NOTICE_CHUANGONG = 11,// 帮派传功
};

enum EGuildDonation
{
	EGoldDonation = 1,		//金币捐献
	EDiamondDonation = 2,	//钻石捐献
	ETicketDonation = 3,	//点券(红钻)捐献
};

// 公会相关lua事件
enum EGuildLuaEvent
{
	ELua_PlayerDonation = 1,	// 玩家捐献
	ELua_UnionLevelUp = 2,		// 玩家升级公会
	ELua_CreateUnion = 3,		// 玩家创建公会
	ELua_DisbandUnion = 4,		// 玩家解散公会
	ELua_JoinUnion = 5,			// 玩家加入公会
	ELua_ChangePos = 6,			// 改变玩家职位
	ELua_KickOut = 7,			// 玩家被踢出公会
	ELua_LeaveUnion = 8,		// 玩家退出公会
	Elua_ApplicationJoin = 9,	// 申请加入
	Elua_ApplicationRefuse = 10,// 申请拒绝
};

enum EGuildRepacketType
{
	ERepacketOtherSystem = 1,	//其他系统红包
	ERepacketSystem = 2,		//本系统红包
	ERepacketPlayer = 3,		//玩家红包
};

enum EGuildRepacketClientType
{
	ERepacketClientSystem = 0,		//系统红包
	ERepacketClientPlayer = 1,		//玩家红包
	ERepacketClientHistory = 2,		//历史红包
};

enum EGuildRepacketState
{
	ERepacketNotGet = 0,		//未领取
	ERepacketGet = 1,			//已领取
	ERepacketClear = 2,			//已抢光
	ERepacketOverTime = 3,		//已超时
};

class CGuild;

class CGuildBoss
{
public:
	typedef std::unordered_map< int32_t, int64_t > TPlayerDamageMap;
	typedef std::unordered_map< int32_t, int32_t > TPlayerUpdateDamageTimeMap;
	typedef std::vector< std::pair<int32_t, int64_t> > TPlayerDamageRankVec;
public:
	CGuildBoss(CGuild& guild);
	~CGuildBoss();

	int32_t boss_id() const { return boss_id_; }
	void set_boss_id(int32_t value) { boss_id_ = value; }

	int64_t boss_maxhp() { return boss_max_hp_; }
	int64_t boss_curhp() { return boss_cur_hp_; }

	int32_t boss_lv() { return boss_lv_; }

	void Clear();

	bool LoadFromJson(Json::Value& boss_json);

	bool SaveToJson(Json::Value& boss_json);

	TPlayerDamageMap& PlayerDamageMap() { return player_damage_map_; }

	void PlayerEnterBoss(int32_t playerid);
	void AddPlayerDamage(int32_t playerid, int32_t damage, bool isdie);
	void BossReduceHp(int32_t playerid, int32_t damage);

	void FillDamageRank(Json::Value& damagerank_json);
	void CalcDamageRank();

	void StartBoss();

	bool isDie();
	

	int32_t GetFirstRankPlayer();
private:
	int32_t boss_id_;
	int32_t boss_lv_;
	int64_t boss_max_hp_;
	int64_t boss_cur_hp_;
	TPlayerDamageMap player_damage_map_;//玩家伤害列表
	TPlayerDamageRankVec player_damage_rank_;
	TPlayerUpdateDamageTimeMap player_update_map_;// 玩家上次上报伤害时间，做个服务器判断，避免客户端作弊频繁上报

	CGuild& guild_;
};

enum EGuildLogType
{
	ELog_Join = 1,		//批准加入公会
	ELog_Kick = 2,		//踢出公会
	ELog_ChangePos = 3,	//改变职位
	ELog_Create = 4,	//创建公会
};

class CGuildLog
{
public:
	CGuildLog()
	{
		op_playerid = 0;
		op_name = "";
		op_type = 0;
		beop_playerid = 0;
		beop_name = "";
		op_time = 0;
		param = 0;
	}
public:
	int32_t op_playerid;	//操作者ID
	std::string op_name;	//操作者名字
	int32_t op_type;		//操作类型
	int32_t beop_playerid;	//被操作者ID
	std::string beop_name;	//被操作者名字
	int32_t op_time;		//操作时间
	int32_t param;
};

// 红包玩家领取列表
class CUnionRepacketInfo
{
public:
	CUnionRepacketInfo()
	{
		m_playerId = 0;
		m_getTime = 0;
		m_getnum = 0;
		m_name = "";
	}
public:
	int32_t m_playerId;					//playerId
	int32_t m_getTime;					//领取时间戳
	int32_t m_getnum;					//领取数量
	std::string m_name;					//领取红包的角色昵称
};
typedef std::unordered_map< int32_t, CUnionRepacketInfo >	TUnionRepacketInfoMap;

// 工会红包
class CUnionRepacket
{
public:
	CUnionRepacket()
	{
		m_idx = 0;
		m_tId = 0;
		m_unionId = 0;
		m_playerId = 0;
		m_name = "";
		m_sendTime = 0;
		m_remainItemCount = 0;
		m_getCount = 0;
		m_createTime = 0;
		m_list.clear();
	}
public:
	int32_t m_idx;					//唯一ID
	int32_t m_tId;					//表ID
	int32_t m_unionId;				//工会IDID
	int32_t m_playerId;				//发红包的角色ID
	std::string m_name;				//发红包的角色昵称
	int32_t m_sendTime;				//发送时间
	int32_t m_remainItemCount;		//剩余物品数量
	int32_t m_getCount;				//已领次数
	int32_t m_createTime;			//创建时间
	TUnionRepacketInfoMap m_list;	//领取列表
};

class CGuild
{
public:
	typedef std::unordered_map< int32_t, CGuildMember >	TGuildMemberMap;
	typedef std::unordered_map< int32_t, int32_t >		TGuildApplyMap;
	typedef std::list< CGuildLog > TGuildLogList;
	typedef std::unordered_map< int32_t, CUnionRepacket >	TCUnionRepacketMap;

	CGuild();
	~CGuild();

	int32_t Clear();
public:
	void set_name(const std::string& name) { guild_name_ = name; }
	void set_icon(const std::string& icon) { guild_icon_ = icon; }
	void set_chairman_player(int32_t player_id) { chairman_player_id_ = player_id; }
	void set_create_player(int32_t player_id) { create_player_id_ = player_id; }
	void set_guild_id(int32_t guild_id) { guild_id_ = guild_id; }
	void set_guilde_lv(int32_t guild_lv) { guild_level_ = guild_lv; }
	void set_guild_exp(int32_t guild_exp) { guild_exp_ = guild_exp; }
	void set_create_time(int32_t time_) { create_time_ = time_; }
	void set_dec(const std::string& dec) { declaration_ = dec; }
	std::string get_name() { return guild_name_; }
	const std::string& get_icon() { return guild_icon_; }
	int32_t get_chairman_player() { return chairman_player_id_; }
	int32_t get_create_player() { return create_player_id_; }
	int32_t get_guild_id() { return guild_id_; }
	int32_t get_guilde_lv() { return guild_level_; }
	int32_t get_guild_exp() { return guild_exp_; }
	int32_t get_create_time() { return create_time_; }
	const std::string& get_dec() { return declaration_; }
	void set_last_save_time(int32_t cur_time) { last_save_time_ = cur_time; }
	void set_minlv(int32_t minlv) { min_limit_lv_ = minlv; }
	int32_t minlimitlv() { return min_limit_lv_; }
	void set_auto_join(int32_t auto_join) { auto_join_ = auto_join; }
	bool auto_join() { return auto_join_ == 1; }
	std::unordered_map<int32_t, CUnionAlcohol> GetAlcohols();
public:
	void GuildInfo2Json(Json::Value& guild_info);

	void SendToGuild(std::string& msg, int32_t msgid);

	int32_t GetMaxMember() const;
	bool IsGuildFull();
	bool IsApplyListFull();
	int32_t CanJoin(CPlayerInfo& playerinfo, EGuildTitle guild_title);
	int32_t JoinGuild(CPlayerInfo& playerinfo, int32_t title);
	void DeleteApply(int32_t playerid);
	void Dissolve();
	int32_t CanApply(int32_t player_id);
	int32_t AddApply(int32_t player_id);
	bool InApplyList(int32_t player_id) const;
	void FillApplyList(Json::Value& item);
	void FillMemberList(Json::Value& item);
	void FillMemberList2(Json::Value& item);
	void FillonlineMemberList(Json::Value& item);
	void FillGuildLog(Json::Value& item);
	CGuildMember* GetMember(int32_t role_id);
	TGuildApplyMap& apply_map() { return apply_map_; }
	TGuildMemberMap& member_map() { return member_map_; }
	int32_t LeaveGuild(int32_t playerid);
	int32_t AppointTitle(CGuildMember& handlers, int32_t role_id, int32_t title);
	void AddGuildLog(int32_t op_playerid, int32_t beopplayerid, int32_t optype, int32_t param = 0);

	int32_t GoldDonation(Player& player);
	int32_t DiamonDonation(Player& player);
	int32_t TicketDonation(Player& player);
	int32_t LevelUp(Player& player);
	void OnNewDay();
	void OnNewWeek();
	bool LoadFromJson(const Json::Value& guild_json);
	bool SaveToJson(Json::Value& guild_json);
	bool SaveApplyToJson(Json::Value& applyjson);
	bool SaveMemberToJson(Json::Value& memberjson);
	bool SaveGuildExToJson(Json::Value& exjson);
	bool SaveGuildRedpacketToJson(Json::Value& rpjson);
	bool LoadApplyFromJson(Json::Value& applyjson);
	bool LoadMemberFromJson(Json::Value& memberjson);
	bool LoadExDataFromJson(Json::Value& exjson);
	bool LoadRedPacketFromJson(Json::Value& redpacketjson);
	int32_t CancelApply(Player& player);

	CGuildMember* GetViceChairman();

	CGuildBoss& GetGuildBoss() { return guild_boss_; }

	void GuildSave();

	void SendMailToGuild(int32_t mail_type, Json::Value& itemlist, Json::Value& param, Json::Value& money);

	void SendChatMessageToGuild(uint32_t, uint32_t, uint32_t, const char*, Player&, uint32_t);
	void SendChatMessageToGuild(uint32_t, uint32_t, uint32_t, const char*, Player&
		, const char*, double, const char*);
public:
	void BossDieNotify();
	void onBossEnd( bool bossdie );
	void KillBoss(int32_t playerId);
public:
	bool UpdateRedpacket(CUnionRepacket kCUnionRepacket);
	void FillRedpacketList(int32_t player_id, int32_t type, Json::Value& redpacketlist_json);
	CUnionRepacket GetUnionRepacketById(int32_t id);
	bool ExsitGetRepacketRewardByPlayerId(int32_t id, int32_t playerid);
	void SendRechargeRedpacket();
private:
	int32_t chairman_player_id_;	//公会会长
	int32_t create_player_id_;		//创建人
	int32_t guild_id_;				//公会ID
	std::string guild_name_;		//公会名称
	std::string guild_icon_;		//图标
	int32_t guild_level_;			//公会等级
	int32_t guild_exp_;				//公会经验
	int32_t create_time_;			//公会创建时间
	std::string declaration_;		//公会宣言
	int32_t today_donation_;		//今日贡献
	bool is_dissovled_;				//是否解散
	int32_t dissovled_time_;		//解散时间
	int32_t last_save_time_;
	int32_t min_limit_lv_;			//限制加入最低等级限制
	int32_t auto_join_;				//自动通过玩家申请入会

	TGuildMemberMap member_map_;	//成员列表
	TGuildApplyMap apply_map_;		//申请列表<playerid, apply_time>
	TGuildLogList guild_log_;		//公会日志,最多存储100条
	TCUnionRepacketMap m_unionRepacket_map_;	//工会红包
	// 公会boss
private:
	CGuildBoss guild_boss_;
};

struct SGuildInvite
{
	SGuildInvite()
	{
		player_id = 0;
		guild_id = 0;
		valid_time = 0;
	}
	int32_t	player_id;
	int32_t	guild_id;
	int32_t	valid_time;
};


class CGuildRankTimer :
	public ::common::CTimer
{
public:
	virtual void TimerActive();
};

class CGuildAlcoholLogic
{
public:
	// 消耗
	static int32_t ReduceCurrency(Player &player, const CUnionAlcohol& alcohol);
	// 将酒的状态存储
	static int32_t SaveAlcoholMembers(Player& player, const CUnionAlcohol& alcohol, Json::Value& target);
};

class CGuildManager :
	public ::common::CSingleton< CGuildManager >
{
public:
	typedef std::unordered_map< int32_t, CGuild* >		TGuildMap;
	typedef std::unordered_map< std::string, CGuild* > 	TGuildNameMap;
	typedef std::list< int32_t > 				TGuildSaveList;
	typedef std::vector< int32_t >				TGuildRankVec;

	struct SGuildComp
	{
		bool operator( )(const int32_t& left, const int32_t& right)
		{
			CGuild* guild_l = CGuildManager::GetInstance().GetGuildByID(left);
			if (NULL == guild_l)
			{
				return false;
			}
			CGuild* guild_r = CGuildManager::GetInstance().GetGuildByID(right);
			if (NULL == guild_r)
			{

				return false;
			}
			if (guild_l->get_guilde_lv() != guild_r->get_guilde_lv())
			{
				return guild_l->get_guilde_lv() > guild_r->get_guilde_lv();
			}
			if (guild_l->member_map().size() != guild_r->member_map().size())
			{
				return guild_l->member_map().size() > guild_r->member_map().size();
			}
			if (guild_l->minlimitlv() != guild_r->minlimitlv())
			{
				return guild_l->minlimitlv() < guild_r->minlimitlv();
			}
			return guild_l->get_create_time() < guild_r->get_create_time();
		}
	};

	CGuildManager();
	~CGuildManager();

	bool Initialize();

	bool Finalize();

	bool LoadGuildDB();

	//加载公会全局数据
	void InitGuildData();
	void LoadGuildData(Json::Value& guilddata);
	void LoadGuildFirstKill(Json::Value& firstKill);
	void SaveGuildFirstKill(Json::Value& firstKill);

	void SaveGuildData();

	CGuild* GetGuildByID(int32_t guild_id);

	CGuild* GetGuildByName(const std::string& guild_name);

	CGuild* CreateGuild(const std::string& guild_name, const std::string& image_id_, CPlayerInfo& player, const std::string& dec, int32_t minlv, int32_t auto_join);

	CGuild* CreateGuild(const Json::Value& guild_data);

	void DissolveGuild(int32_t guild_id);

	void UpdateGuildRank();

	const TGuildMap& guild_map() const { return guild_map_; }

	const TGuildRankVec& guild_rank_vec() const { return guild_rank_vec_; }

	int32_t ApplyGuild(int32_t playerid, CGuild& guild);

	int32_t ReplyApply(Player& player, int32_t dest_id, bool agree);

	//自动同意加入公会
	int32_t autoApply(CGuild& guild, int32_t destid);

	int32_t JoinGuild(CPlayerInfo& player, CGuild& guild, EGuildTitle title);

	int32_t LeaveGuild(CGuild& guild, int32_t playerid);

	int32_t KickoutGuild(CGuild& guild, int32_t playerid, int32_t dest_id);

	void CheckInValidCampGuild();

	void OnNewDay();
	void OnNewWeek();

	int32_t GuildBossCall(int32_t role_id, int32_t boss_id);

	int32_t GuildBossEnter(int32_t role_id);

	void TickUpdate();

	void SaveGuild();

	void ReGuildLevel();

	//int32_t GuildSaveLeft( ) { return save_list_.DirtyListSize( ); }
	int32_t GuildSaveLeft() { return guild_map_.size() - exit_saved_guild_.size(); }

	void FillGuildToJson(Json::Value& res, int32_t start, int32_t count);
	void GetPlayerApplyList(Json::Value& auj, int32_t playerid);
	void ApplyListNotify(CGuild& guild, int32_t playerid);

	void GuildChangeName(std::string& oldname, CGuild& guild);

	int32_t GetGuildRank(int32_t guildid);

	void GetUnionInfoById(int32_t guildid, std::string& unioninfo);
	void GetUnionApplyList(int32_t guildid, std::string& applylist);

	void GuildBossStart();
	void GuildBossEnd();
	void GuildBossNotify();
	void GuildEnterBoss(CGuild& guild);
	void CalcFirstKill(CGuild& guild, int32_t bossid, int32_t bosslv, int32_t playerid);
	int32_t GetGuildBossActivityID();

	////////////////////红包//////////////////////////////////
	int32_t GetRedpacketIdMax() { return redpacket_id_max_; }
	void SetRedpacketIdMax(int32_t id) { redpacket_id_max_ = id; }

private:
	void AddGuild(CGuild& guild);
	int32_t RefreshGuildIDMax(int32_t guild_id);
	/// @brief      检测其它系统此时是否允许踢人、解散;
	/// @param      CGuild guild
	/// @return     int32_t
	int32_t CheckKickoutGuildConflict(const CGuild& guild);
	TGuildMap guild_map_;
	TGuildNameMap guild_name_map_;
	TGuildRankVec guild_rank_vec_; // 排行榜:id
	int32_t guild_id_max_;
	int32_t redpacket_id_max_;	   // 当前红包id的最大值，下一个新红包的id时加1

	// bossID， 玩家ID
	std::unordered_map<int32_t, int32_t> boss_first_kill_;	//公会boss首杀表

	CGuildRankTimer guild_rank_timer_; // 公会排名定时器
	time_t update_sec_;

	std::set<int32_t>	exit_saved_guild_; // 退出时用来标识是否存储过

	std::set<int32_t> guild_boss_enter_;	// 有参与公会boss的公会,临时记录
};

#endif

